package com.tanhua.server.service;

import cn.hutool.core.collection.CollUtil;
import com.tanhua.autoconfig.template.OssTemplate;
import com.tanhua.commons.utils.Constants;
import com.tanhua.dubbo.api.UserInfoApi;
import com.tanhua.dubbo.api.mongo.MovementApi;
import com.tanhua.dubbo.api.mongo.VisitorsApi;
import com.tanhua.model.domain.UserInfo;
import com.tanhua.model.mongo.Movement;
import com.tanhua.model.mongo.Visitors;
import com.tanhua.model.vo.ErrorResult;
import com.tanhua.model.vo.MovementsVo;
import com.tanhua.model.vo.PageResult;
import com.tanhua.model.vo.VisitorsVo;
import com.tanhua.server.exception.BusinessException;
import com.tanhua.server.interceptor.UserHolder;
import org.apache.dubbo.config.annotation.DubboReference;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
public class MovementsService {

    @Autowired
    private OssTemplate ossTemplate;

    @DubboReference
    private MovementApi movementApi;

    @DubboReference
    private UserInfoApi userInfoApi;

    @DubboReference
    private VisitorsApi visitorsApi;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Autowired
    private MqMessageService mqMessageService;


    public void saveMovements(Movement movement, MultipartFile[] imageContent) throws IOException {
        //检测是否冻结
        String reason = redisTemplate.opsForValue().get(Constants.FreezeMovement_KEY + UserHolder.getId());
        Long restTime = redisTemplate.opsForValue().getOperations().getExpire(Constants.FreezeMovement_KEY + UserHolder.getId(), TimeUnit.HOURS);
        if (reason != null) {
            throw new BusinessException("该用户处于冻结发动态状态, 请联系客户处理", ErrorResult.freezeMovementError("\n 解除冻结剩余时间"+restTime+"小时"+"\n 冻结原因"+reason));
        }

        List<String> imageList = new ArrayList<>();
        if (imageContent != null && imageContent.length != 0) {
            for (MultipartFile image : imageContent) {
                String imageUrl = ossTemplate.upload(image.getOriginalFilename(), image.getInputStream());
                imageList.add(imageUrl);
            }
        }
        movement.setCreated(System.currentTimeMillis());
        movement.setUserId(UserHolder.getId());
        movement.setMedias(imageList);
        movement.setId(ObjectId.get());
        movementApi.saveMovements(movement);

        mqMessageService.sendAudiService(movement.getId().toString());
        mqMessageService.sendLogService(UserHolder.getId(),"0201","movement",movement.getId().toString());
    }

    public PageResult findByUserId(Integer page, Integer pagesize, Long userId) {
        PageResult pageResult = movementApi.findMovements(page, pagesize, userId,null);
        List<Movement> movements = (List<Movement>) pageResult.getItems();
        UserInfo userInfo = userInfoApi.findById(userId);
        List<MovementsVo> voList = new ArrayList<>();
        for (Movement movement : movements) {
            MovementsVo vo = MovementsVo.init(userInfo, movement);
            isLikeOrLove(movement.getId().toString(), vo);
            voList.add(vo);
        }
        pageResult.setItems(voList);
        return pageResult;
    }

    public PageResult movements(Integer page, Integer pagesize) {
        Long userId = UserHolder.getId();
        PageResult pageResult = movementApi.findFriendsMovements(page, pagesize, userId);
        List<Movement> movementList = (List<Movement>) pageResult.getItems();
        List<Long> userIds = CollUtil.getFieldValues(movementList, "userId", Long.class);
        Map<Long, UserInfo> userInfoMap = userInfoApi.findByIds(userIds);
        List<MovementsVo> voList = new ArrayList<>();
        for (Movement movement : movementList) {
            UserInfo userInfo = userInfoMap.get(movement.getUserId());
            MovementsVo vo = MovementsVo.init(userInfo, movement);
            isLikeOrLove(movement.getId().toString(), vo);
            voList.add(vo);
        }
        pageResult.setItems(voList);
        return pageResult;
    }

    public PageResult recommend(Integer page, Integer pagesize) {
        Long userId = UserHolder.getId();
        String key = Constants.MOVEMENTS_RECOMMEND + userId;
        String pids = redisTemplate.opsForValue().get(key);
        List<Movement> movementList = null;
        String[] pidsArray = null;
        if (StringUtils.isEmpty(pids)) {
            movementList = movementApi.ramdomMovements(pagesize);  //随机产生推荐动态
        } else {
            pidsArray = pids.split(",");
            if ((page - 1) * pagesize >= pidsArray.length) {
                movementList = new ArrayList<>();
            } else {
                List<Long> pidList = Arrays.stream(pidsArray).skip((page - 1) * pagesize).limit(pagesize)
                        .map(pid -> {
                            return Long.valueOf(pid);
                        })
                        .collect(Collectors.toList());
                movementList = movementApi.findByPids(pidList);
            }
        }
        List<Long> userIds = CollUtil.getFieldValues(movementList, "userId", Long.class);
        Map<Long, UserInfo> userInfoMap = userInfoApi.findByIds(userIds);
        List<MovementsVo> voList = new ArrayList<>();
        for (Movement movement : movementList) {
            UserInfo userInfo = userInfoMap.get(movement.getUserId());
            MovementsVo vo = MovementsVo.init(userInfo, movement);
            isLikeOrLove(movement.getId().toString(), vo);
            voList.add(vo);
        }
        Integer counts = pids == null ? pagesize : pidsArray.length;
        return new PageResult(page.longValue(), pagesize.longValue(), counts.longValue(), voList);

    }

    public MovementsVo findById(String movementId) {
        Movement movement = movementApi.findById(movementId);
        if (movement != null) {
            UserInfo userInfo = userInfoApi.findById(movement.getUserId());
            MovementsVo vo = MovementsVo.init(userInfo, movement);
            mqMessageService.sendLogService(UserHolder.getId(),"0202","movement",movementId);
            return vo;
        }
        return null;
    }

    public void isLikeOrLove(String movementId, MovementsVo vo) {
        String key1 = Constants.USER_LIKE_KEY + movementId + "_" + UserHolder.getId();
        if (redisTemplate.hasKey(key1)) {
            vo.setHasLiked(1);
        }
        String key2 = Constants.MOVEMENT_LOVE_HASHKEY + movementId + "_" + UserHolder.getId();
        if (redisTemplate.hasKey(key2)) {
            vo.setHasLoved(1);
        }
    }

    public List<VisitorsVo> queryVisitorsList() {
        String key = Constants.VISITORS_USER;
        String field = UserHolder.getId().toString();
        HashOperations<String, Object, Object> opsForHash = redisTemplate.opsForHash();
        Long lastTime = opsForHash.get(key, field) == null ? null : Long.valueOf(opsForHash.get(key, field).toString());
        List<Visitors> visitorsList = visitorsApi.queryVisitorsList(UserHolder.getId(), lastTime);
        List<Long> visitorUserId = CollUtil.getFieldValues(visitorsList, "visitorUserId", Long.class);
        Map<Long, UserInfo> userInfoMap = userInfoApi.findByIds(visitorUserId);
        List<VisitorsVo> visitorsVos = new ArrayList<>();
        for (Visitors visitors : visitorsList) {
            UserInfo userInfo = userInfoMap.get(visitors.getVisitorUserId());
            VisitorsVo vo = VisitorsVo.init(userInfo, visitors);
            visitorsVos.add(vo);
        }
        return visitorsVos;
    }
}